#include "Stdafx.h"
#include "vcclr.h"

#include "ZmqContext.h"
#include <locale>

using namespace System;
using namespace System::Threading;

namespace vJine {
	namespace ZMQ {
		ZmqContext::ZmqContext() {

			this->context = zmq_ctx_new();
			if(this->context == NULL) {
				ZmqContext::throw_ex("ZmqContext.ctor()");
			}

		}

		ZmqContext::~ZmqContext() {
			
			this->Close();

		}

		void ZmqContext::Close() {

			Monitor::Enter(this);
			try{
				if(this->context == NULL) {
					return;
				}

				if(zmq_ctx_term(this->context) == -1) {
					ZmqContext::throw_ex("ZmqContext.Close()");
				}
				
				this->context = NULL;
			} finally {
				Monitor::Exit(this);
			}

		};

		ZmqSocket^ ZmqContext::Create(ZmqRole role) {
			Monitor::Enter(this);
			try{
				return gcnew ZmqSocket(this->context, role);
			} finally {
				Monitor::Exit(this);
			}
		}

		ZmqSocket^ ZmqContext::Bind(ZmqRole role, String^ endpoint) {

			Monitor::Enter(this);
			try{
				ZmqSocket^ zmqSocket = gcnew ZmqSocket(this->context, role);
				zmqSocket->Bind(endpoint);

				return zmqSocket;
			} finally {
				Monitor::Exit(this);
			}

		};

		ZmqSocket^ ZmqContext::Connect(ZmqRole role, String^ endpoint) {

			Monitor::Enter(this);
			try {
				ZmqSocket^ zmqSocket = gcnew ZmqSocket(this->context, role);
				zmqSocket->Connect(endpoint);
				
				return zmqSocket;
			} finally {
				Monitor::Exit(this);
			}

		}

		String^ ZmqContext::Version::get() {
			int major, minor, patch;
					zmq_version(&major, &minor, &patch);
					return 
						major.ToString() 
						+ "." + minor.ToString() 
						+ "." + patch.ToString();
		}

		int ZmqContext::io_threads::get() {
			return zmq_ctx_get(this->context, ZMQ_IO_THREADS);
		}
		void ZmqContext::io_threads::set(int value) {
			if(zmq_ctx_set(this->context, ZMQ_IO_THREADS, value) == -1) {
				ZmqContext::throw_ex("ZmqContext.io_threads.set(int value)");
			}
		}

		int ZmqContext::max_sockets::get() {
			return zmq_ctx_get(this->context, ZMQ_MAX_SOCKETS);
		}
		void ZmqContext::max_sockets::set(int value) {
			if(zmq_ctx_set(this->context, ZMQ_MAX_SOCKETS, value) == -1) {
				ZmqContext::throw_ex("ZmqContext.max_sockets.set(int value)");
			}
		}

		bool ZmqContext::ipv6::get() {
			return zmq_ctx_get(this->context, ZMQ_IPV6) == 1;
		}
		void ZmqContext::ipv6::set(bool value) {
			if(zmq_ctx_set(this->context, ZMQ_IPV6, (ZMQ_IPV6, value ? 1 : 0)) == -1) {
				ZmqContext::throw_ex("ZmqContext.ipv6.set(bool value)");
			}
		}

		void ZmqContext::throw_ex(String^ fcn_name) {
			throw gcnew ZmqException(fcn_name + ", Ex: " + gcnew String(zmq_strerror(zmq_errno())));
		}

		void ZmqContext::throw_ex(String^ fcn_name, String^ err_msg) {
			throw gcnew ZmqException(fcn_name + ", Ex: " + err_msg);
		}
	}
}